
#include <util/mem.h>
#include <util/common_macros.h>

#include "vertex.h"
#include "segment.h"

static long int count = 0;
void imp_vertex_set_count(long int c) {
	count = 0;
}
/* ========================================================================== */
static boolean __vertex_destroy(ImpObject * object) {
	ImpVertex * v;
	ListIterator * it;

	v = IMP_VERTEX(object);

	it = v->segments->first;
	while (it) {
		imp_object_destroy(IMP_OBJECT(it->data));
		it = it->next;
	}

	if (v->segments) {
		list_remove_all_data(v->segments);
		list_delete(v->segments);
	}

	v->segments = NULL;
	return TRUE;
}
static void __vertex_class_init(ImpObjectClass * klass) {
	klass->object_clone = NULL;
	klass->object_destroy = __vertex_destroy;
	klass->object_attributes = NULL;
}
static void __vertex_init(ImpObject * object) {
	ImpVertex * v;

	v = IMP_VERTEX(object);
	v->segments = NULL;

}
/* ========================================================================== */

ImpVertexClass * imp_vertex_get_class(void) {
	static ImpVertexClass * klass = NULL;

	if (klass == NULL) {
		ImpObjectClassInfo vertex_info = {
										"ImpVertex",
										sizeof (ImpVertex),
										sizeof (ImpVertexClass),
										(ImpObjectClassInitFunc) __vertex_class_init,
										(ImpObjectInitFunc) __vertex_init,
										(ImpArgSetFunc) NULL,
										(ImpArgGetFunc) NULL
		};

		ImpObjectClass * parent_class = IMP_OBJECT_CLASS(imp_point_get_class());
		ImpObjectClass * vertex_class = imp_object_class_new(parent_class, &vertex_info);
		klass = IMP_VERTEX_CLASS(vertex_class);
	}
	return klass;
}
ImpVertex * imp_vertex_new(real x, real y, real z) {
	ImpVertex * v;

	v = IMP_VERTEX(imp_object_new(IMP_OBJECT_CLASS(imp_vertex_get_class())));

	v->segments = list_new();

	imp_vertex_set(v, x, y, z);



	return v;
}
void imp_vertex_set(ImpVertex * v, real x, real y, real z) {
	imp_point_set(IMP_POINT(v), x, y, z);

	v->id = ++count;

}
ImpVertex * imp_vertex_new_from_point(ImpPoint p) {
	ImpVertex * v;
	v = imp_vertex_new(p.x, p.y, p.z);
	return v;
}
/* ========================================================================== */

real imp_vertex_compare(ImpVertex * v1, ImpVertex * v2) {

	real dx, dy, dz;

	dx = IMP_POINT(v1)->x - IMP_POINT(v2)->x;
	if (dx) return dx;

	dy = IMP_POINT(v1)->y - IMP_POINT(v2)->y;
	if (dy) return dy;

	dz = IMP_POINT(v1)->z - IMP_POINT(v2)->z;
	if (dz) return dz;

	return 0.0;
}
/* ========================================================================== */

void imp_vertex_add_segment(ImpVertex * v, ImpSegment * s) {
	list_append(v->segments, s);
}
ImpSegment * imp_vertex_remove_segment(ImpVertex * v, ImpSegment * s) {
	return list_remove_data(v->segments, s);
}
/* ========================================================================== */

boolean imp_vertex_have_segment(ImpVertex * v, ImpSegment * s) {
	return ( list_have_data(v->segments, s) != NULL);
}
/* ========================================================================== */

void imp_vertex_print(ImpVertex * v) {

	if (!v) {
		printf("NULL");
		return;
	}

	printf("p%i", v->id);
	imp_point_print(IMP_POINT(v));

}
